package com.cqd.qxdemo

import android.Manifest
import android.app.PendingIntent
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.hardware.usb.UsbDevice
import android.hardware.usb.UsbManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.SpannableStringBuilder
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.EditText
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.qx.wz.common.bean.QxLocation
import com.qx.wz.deviceadapter.usb.usbserial.driver.UsbSerialPort
import com.qx.wz.deviceadapter.usb.usbserial.driver.UsbSerialProber
import com.qx.wz.magic.location.Options
import com.qx.wz.magic.location.QxLocationListener
import com.qx.wz.magic.location.QxLocationManager
import java.io.IOException
import java.util.concurrent.Executors

/**
 * author:CQD

 * e-mail:634897993@qq.com

 * data:  2020/4/17

 * desc:
 *
 * version:
 */
class QxActivity : AppCompatActivity(),
    QxLocationListener,SerialInputOutputManager.Listener {

    /**
     * usb 权限状态
     */
    private enum class UsbPermission {
        Unknown, Requested, Granted, Denied
    }

    private val INTENT_ACTION_GRANT_USB: String = BuildConfig.APPLICATION_ID + ".GRANT_USB"
    private val WRITE_WAIT_MILLIS = 2000
    private val READ_WAIT_MILLIS = 2000

    private var baudRate = 9600

    private var broadcastReceiver: BroadcastReceiver? = null

    private var mainLooper: Handler? = null

    //usb 权限状态
    private var usbPermission = UsbPermission.Unknown

    private var usbSerialPort: UsbSerialPort? = null
    private var usbIoManager: SerialInputOutputManager? = null

    private var connected = false

    private var mTextView: TextView? = null
    private var mTvContent: TextView? = null
    private var mTvClose: Button? = null
    private var display: TextView? = null

    init {
        broadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(
                context: Context,
                intent: Intent
            ) { //usb授权弹窗广播
                if (intent.action == INTENT_ACTION_GRANT_USB) {
                    usbPermission = if (intent.getBooleanExtra(
                            UsbManager.EXTRA_PERMISSION_GRANTED,
                            false
                        )
                    ) UsbPermission.Granted else UsbPermission.Denied

                }
            }
        }
        mainLooper = Handler(Looper.getMainLooper())
    }

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_qx)
        initView()

    }

    private fun initView(){
        mTextView = findViewById(R.id.test)
        mTvContent = findViewById(R.id.tv_content)
        mTvClose = findViewById(R.id.tv_close)
        mTvClose?.setOnClickListener {
            // 移除千寻SDK listener，如果当前listener是最后一个，则会自动关闭千寻SDK功能
            QxLocationManager.getInstance().removeUpdates(this@QxActivity)
            // 清除SDK内存缓存和释放资源
            QxLocationManager.getInstance().close()
            mTextView?.text = ""
            mTvContent?.text = ""
        }
        display = findViewById<View>(R.id.textView1) as TextView


        val tv_open =
            findViewById<View>(R.id.tv_open) as Button
        tv_open.setOnClickListener { initQx() }

        val open =
            findViewById<View>(R.id.open) as Button
        open.setOnClickListener {
            connect()
        }
        val close =
            findViewById<View>(R.id.close) as Button
        close.setOnClickListener {
            disconnect()
        }
//        val sendButton =
//            findViewById<View>(R.id.buttonSend) as Button
//        sendButton.setOnClickListener {
//            val mOrder = byteArrayOf(
//                0x66.toByte(),
//                0x65.toByte(),
//                0x6E.toByte(),
//                0x67.toByte(),
//                0x79.toByte(),
//                0x69.toByte(),
//                0x6E.toByte()
//                ,
//                0x67.toByte(),
//                0x64.toByte(),
//                0x69.toByte(),
//                0x61.toByte(),
//                0x6E.toByte(),
//                0x7A.toByte(),
//                0x69.toByte(),
//                0x3A.toByte()
//                ,
//                0xAB.toByte(),
//                0x06.toByte(),
//                0x47.toByte(),
//                0x50.toByte(),
//                0x53.toByte(),
//                0x52.toByte(),
//                0x54.toByte(),
//                0x4B.toByte()
//                ,
//                0x9C.toByte()
//            )
//            usbSerialPort?.write(mOrder,WRITE_WAIT_MILLIS)
//        }
    }

    private fun initQx() {
        /**
         * 登录千寻位置网官网的开发者管理控制台创建应用，成功后会自动生成该应用的AppKey和AppSerect；AppKey和AppSecret是应用的凭证信息，请妥善保管。详细信息请见千寻官网帮助文档。SDK使用需要使用AppKey、AppSecret、DeviceId、DeviceType。
         * 1. DeviceId和DeviceType联合组成设备唯一值，从而能够区分设备。在同一个AppKey下， 需保证这两个值联合唯一，一般情况同Appkey下DeviceType值是相同的；
         * 2. DeviceId 表示设备号。建议使用终端用户可以看到的值，系统生成的类似UUID值用户可能是看不见的。 建议使用用户可在产品上查到的值。后续比如用户报障，续费使用等问题都可方便的进行解决。 因此推荐使用印刷在终端设备上的SN、IMEI等值；
         * 3. DeviceType表示设备类型。 语义是用来区分设备关键型号。例如关键的传感器类型，可区分不同的产品值等。 要求填写有意义的值，如果是App集成推荐使用应用名称（字母）。如果是嵌入式终端智能产品推荐使用产品名称。 这个值可用于为不同产品设置不同的配置信息。
         */
        val appKey = "A48c0vep64kp"
        val appSecret =
            "f6f5f033c3fba6e5170bc9a0a44fc259fd47b1b573afeafa2a3a02da6e15422d"
        val deviceId = "ceshizhanghao110"
        val deviceType = "SKYDROID"
        // 构造千寻SDK必须输入参数，context、appKey、appSecret、deviceType、deviceId是千寻SDK必须输入
//使用千寻魔方数据provider使用QxLocationManager.DEVICE_PROVIDER，开发人员无设备仅是模拟测试使用QxLocationManager.MOCK_PROVIDER
//硬件主板集成千寻魔方方案，serialPath不能为空，必须传入千寻魔方驱动设备节点路径（由硬件方案商提供）；通过USB线外接设备集成千寻魔方方案，serialPath为空或者不要设置即可。
        val options = Options.Builder()
            .context(applicationContext)
            .appKey(appKey)
            .appSecret(appSecret)
            .deviceId(deviceId)
            .deviceType(deviceType)
            .provider(QxLocationManager.DEVICE_PROVIDER) //                .serialPath("千寻魔方驱动设备节点（由硬件方案上提供）")
            .build()
        //切记，使用之前确保相关权限已经授权，这部分由集成方负责
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
            ) == PackageManager.PERMISSION_GRANTED &&
            ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            QxLocationManager.getInstance().init(options)
        }
        // 启动千寻SDK，结果通过onLocationChanged返回
        QxLocationManager.getInstance().requestLocationUpdates(this, null)
    }

    override fun onDestroy() {
        super.onDestroy()
        //        // 移除千寻SDK listener，如果当前listener是最后一个，则会自动关闭千寻SDK功能
//        QxLocationManager.getInstance().removeUpdates(this);
//        // 清除SDK内存缓存和释放资源
//        QxLocationManager.getInstance().close();
    }

    override fun onResume() {
        super.onResume()
        registerReceiver(broadcastReceiver,  IntentFilter(INTENT_ACTION_GRANT_USB))
    }

    override fun onPause() {
        if (connected) {
            disconnect()
        }
        unregisterReceiver(broadcastReceiver)
        super.onPause()
    }

    override fun onLocationChanged(qxLocation: QxLocation) { // 千寻SDK返回位置
        runOnUiThread {
            mTvContent!!.text = "lat:" + qxLocation.latitude + " lng:" + qxLocation.longitude
            //                mTvContent.setText(qxLocation.getProvider() + "");
        }
    }

    override fun onStatusChanged(
        i: Int,
        bundle: Bundle?
    ) { // 千寻SDK返回状态，状态码详细见
        runOnUiThread {
            Log.e("tag", "status:$i")
            mTextView!!.text = "status:$i"
        }
    }

    override fun onNmeaReceived(s: String?) {}

    /*
     * Serial + UI
     */
    private fun connect() {
        var device: UsbDevice? = null
        val usbManager = getSystemService(Context.USB_SERVICE) as UsbManager
        usbManager.deviceList?.values?.forEach {
            device = it
        }

        if (device == null) {
            Toast.makeText(this,"未找到设备", Toast.LENGTH_SHORT).show()
            return
        }
        var driver = UsbSerialProber.getDefaultProber().probeDevice(device)
        if (driver == null) {
            driver = CustomProber.getCustomProber()?.probeDevice(device)
        }
        if (driver == null) {
            Toast.makeText(this,"不支持该设备", Toast.LENGTH_SHORT).show()
            return
        }
//        if (driver.ports.size < portNum) {
//            status("connection failed: not enough ports at device")
//            return
//        }
        usbSerialPort = driver.ports[0]
        val usbConnection = usbManager.openDevice(driver.device)
        //判断是否可用
        if (usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.device)) {
            //标记为请求中
            usbPermission = UsbPermission.Requested
            val usbPermissionIntent =
                PendingIntent.getBroadcast(
                    this,
                    0,
                    Intent(INTENT_ACTION_GRANT_USB),
                    0
                )
            usbManager.requestPermission(driver.device, usbPermissionIntent)
            return
        }
        if (usbConnection == null) {

//            if (!usbManager.hasPermission(driver.device)) status("connection failed: permission denied") else status(
//                "connection failed: open failed"
//            )
            return
        }
        try {
            usbSerialPort?.open(usbConnection)
            usbSerialPort?.setParameters(
                baudRate,
                UsbSerialPort.DATABITS_8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE
            )

            usbSerialPort?.setDTR(true) // for arduino, ...
            usbSerialPort?.setRTS(true)
            usbIoManager = SerialInputOutputManager(usbSerialPort, this)
            Executors.newSingleThreadExecutor().submit(usbIoManager)
            connected = true
        } catch (e: java.lang.Exception) {
//            status("connection failed: " + e.message)
            disconnect()
        }
    }

    private fun disconnect() {
        connected = false
        usbIoManager?.listener = null
        usbIoManager?.stop()
        usbIoManager = null

        try {
            usbSerialPort?.setDTR(false)
            usbSerialPort?.setRTS(false)
            usbSerialPort?.close()
        } catch (ignored: IOException) {
        }finally {
            usbSerialPort = null
        }

    }

    private fun receive(data: ByteArray?) {
        val spn = SpannableStringBuilder()
        spn.append("receive " + data?.size + " bytes\n")
        if (data?.size?:0 > 0) spn.append(HexDump.dumpHexString(data).toString() + "\n")
        display?.append(spn)
    }

    override fun onRunError(e: Exception?) {

    }

    override fun onNewData(data: ByteArray?) {
        mainLooper?.post { receive(data) }
    }
}
